package com.atjava.webspider.thread;

import java.util.HashMap;
import java.util.LinkedList;

import com.atjava.webspider.logic.ConfigLogic;
import com.atjava.webspider.thread.infs.NamedTask;

public class TaskQueue {
	private final HashMap<Object, ThreadWorker> threads;
	private final LinkedList<NamedTask> queue;
	private int queueSize;
	private boolean started;

	public TaskQueue(int queueSize) {
		this.queue = new LinkedList<NamedTask>();
		this.threads = new HashMap<Object, ThreadWorker>();
		this.queueSize = queueSize;
	}
	
	public TaskQueue(){
		this(ConfigLogic.getAppConfig().getWorkThreads());
	}

	public void execute(NamedTask r) {
		synchronized (queue) {
			r.waitting();
			queue.addLast(r);
			queue.notify();
		}
	}
	
	public void startup(){
		started = true;
		for (int i = 0; i < queueSize; i++) {
			new ThreadWorker().start();
		}
	}
	
	public void shutdown(){
		started = false;
	}
	
	public void stop(Object... ids){
		for (int i = 0; i < ids.length; i++) {
			threads.get(ids[i]).stopWork();
		}
	}
	
	public void pause(Object... ids){
		for (int i = 0; i < ids.length; i++) {
			threads.get(ids[i]).pauseWork();
		}
	}
	
	public void goon(Object... ids){
		for (int i = 0; i < ids.length; i++) {
			threads.get(ids[i]).goonWork();
		}
	}

	private class ThreadWorker extends Thread {
		private NamedTask task;
		public ThreadWorker(){}
		public void stopWork(){
			task.stop();
		}
		public void pauseWork(){
			task.pause();
		}
		
		public void goonWork(){
			task.goon();
		}
		
		public void run() {
			while(started){
				synchronized (queue) {
					if (queue.isEmpty()) {
						try {
							queue.wait();
						} catch (InterruptedException ignored) {}
					}
					task = (NamedTask) queue.removeFirst();
				}
				try {
					threads.put(task.getName(), this);
					task.run();
				} catch (RuntimeException e) {
					e.printStackTrace();
				}
			}
		}
	}
	public static void main(String[] args) throws Exception{
		
		TaskQueue tp = new TaskQueue(2);
		tp.startup();
		tp.execute(new TestThread("a"));
		tp.execute(new TestThread("b"));
		tp.execute(new TestThread("c"));
		tp.execute(new TestThread("d"));
		
		tp.pause("b");
		Thread.sleep(1000);
		tp.goon("b");
		
	}
}
